package com.sxjh.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.auth0.jwt.JWT;
import com.sxjh.annotation.UserLog;
import com.sxjh.common.Result;
import com.sxjh.entity.User;
import com.sxjh.entity.UserActionLogs;
import com.sxjh.mapper.UserActionLogsMapper;
import com.sxjh.service.UserActionLogsService;
import com.sxjh.service.UserService;
import com.sxjh.uitl.IPUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Slf4j
@Service
public class UserActionLogsServiceImpl implements UserActionLogsService {

  @Resource
  private UserActionLogsMapper userActionLogsMapper;
  @Resource
  private UserService userService;

  @Override
  public int save(UserActionLogs userActionLogs) {
    return userActionLogsMapper.insert(userActionLogs);
  }

//  @Async("taskExecutor")
  @Override
  public void saveLog(ProceedingJoinPoint joinPoint, Object result, HttpServletRequest request) {
    if(!(result instanceof Result)){
      //返回对象不是result，不记录
      return ;
    }
    Result res = (Result) result;
    Integer code = res.getCode();
    if(code.intValue() != 200){
      //不是成功，不记录
      return ;
    }

    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();

    UserLog actionLog = method.getAnnotation(UserLog.class);
    String desc = actionLog.desc();
    String roleCode = actionLog.roleCode();
    if(res.getData() instanceof String){
      desc = desc + " " + res.getData();
    }
    String resCode = String.valueOf(res.getCode());
    String resMsg = res.getMsg();


    UserActionLogs actionLogs = new UserActionLogs();
    //请求的方法名
    actionLogs.setDescription(desc);
    actionLogs.setRouteName(roleCode);
    actionLogs.setResponseCode(resCode);
    actionLogs.setResponseMsg(resMsg);

    //请求的参数
    Object[] args = joinPoint.getArgs();
    try{
      actionLogs.setParameters(JSONUtil.toJsonStr(args));
    }catch (Exception e){
      log.error("保存操作日志-封装请求参数异常", e);
    }

    //设置IP地址
    actionLogs.setRequestIp(IPUtils.getIpAddr(request));
    //设置请求链接
    actionLogs.setRequestUrl(request.getRequestURI());
    actionLogs.setRequestMethod(request.getMethod());

    //用户名
    String token = request.getHeader("Authorization");
    User user = this.getUserByToken(token);
    if(user != null){
      actionLogs.setUserId(user.getId());
      actionLogs.setUserName(user.getName());
    }

    LocalDateTime currentTime = LocalDateTime.now();
    actionLogs.setCreatedAt(currentTime);
    actionLogs.setUpdatedAt(currentTime);

    this.save(actionLogs);
  }

  /**
   * 根据 token 获取用户信息
   * @param token
   * @return
   */
  private User getUserByToken(String token){
    if (StrUtil.isEmpty(token) || token.length() < 8) {
      log.error("保存操作日志-令牌格式不正确：{}", token);
      return null;
    }
    String token2 = token.substring(7);
    // 设置用户信息
    Integer id = null;
    try {
      id = JWT.decode(token2).getClaim("sub").asInt();
    } catch (Exception e) {
    }
    if (null == id) {
      log.error("保存操作日志-令牌内容异常，获取不了用户id：{}", token);
      return null;
    }
    User user = userService.getUser(id);
    return user;
  }
}
